package com.lyncs.ods.modules.setting.service.impl;

import cn.hutool.crypto.digest.MD5;
import com.lyncs.ods.common.exception.ApiException;
import com.lyncs.ods.constant.LyncsOdsConstant;
import com.lyncs.ods.modules.setting.model.ShortLinkInfo;
import com.lyncs.ods.modules.setting.mapper.ShortLinkInfoMapper;
import com.lyncs.ods.modules.setting.service.ShortLinkInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyncs.ods.utils.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 短链信息表 服务实现类
 * </p>
 *
 * @author alex
 * @since 2022-05-31
 */
@Service
public class ShortLinkInfoServiceImpl extends ServiceImpl<ShortLinkInfoMapper, ShortLinkInfo> implements ShortLinkInfoService {

    public static final String FORMAT_URL = "{0}/#/share/{1}?cidA={2}&detailId={3}&cidB={4}";

    @Value("${app.host}")
    private String appHost;

    @Override
    public ShortLinkInfo generateShortLink(LyncsOdsConstant.TxnType type, Long refId, Long invitor, Long invited) {
        String completeUrl = MessageFormat.format(FORMAT_URL, appHost, type.getValue(), invitor.toString(), refId.toString(), invited.toString());
        return generateShortLink(completeUrl, type.getKey(), refId);
    }

    @Override
    public String generateShortLink(@NotNull String completeUrl, LyncsOdsConstant.TxnType type, Long refId) {
        return generateShortLink(completeUrl, type.getKey(), refId).getDeeplink();
    }

    private ShortLinkInfo generateShortLink(String completeUrl, Integer type, Long refId) {
        String salt = getSalt(completeUrl);
        ShortLinkInfo linkInfo = this.lambdaQuery().eq(ShortLinkInfo::getSalt, salt).one();
        if (Objects.nonNull(linkInfo)) {
            return linkInfo;
        }

        String key = getKey();
        String deeplink = StringUtils.join(appHost, LyncsOdsConstant.Common.REV_BIAS, key);
        ShortLinkInfo shortLinkInfo = new ShortLinkInfo()
                .setType(type)
                .setRefId(refId)
                .setKey(key)
                .setDeeplink(deeplink)
                .setUrl(completeUrl)
                .setSalt(salt)
                .setCreateTime(LocalDateTime.now());
        this.save(shortLinkInfo);
        return shortLinkInfo;
    }

    @Override
    public String getLinkByKey(String key) {
        ShortLinkInfo linkInfo = this.lambdaQuery().eq(ShortLinkInfo::getKey, key).one();
        if (Objects.isNull(linkInfo)) {
            throw new ApiException("请输入正确的地址");
        }
        return linkInfo.getUrl();
    }

    @Override
    public String generateShortLink(String url) {
        Integer type = null;
        return generateShortLink(url, type, null).getDeeplink();
    }

    private String getKey() {
        String key = null;
        boolean exist = Boolean.TRUE;
        while (exist) {
            key = RandomUtils.generate().toLowerCase();
            exist = this.lambdaQuery().eq(ShortLinkInfo::getKey, key).count() > 0;
        }
        return key;
    }

    private String getSalt(String url) {
        return MD5.create().digestHex16(url);
    }
}
